﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;
using Beeldbankmvc.Models;
using System.Configuration;
using System.Text.RegularExpressions;


namespace Beeldbankmvc.Code
{
    public static class Gebied
    {
        public static Image drawAreasOnMapIndex(double? topLeftLat, double? topLeftLon, double? bottomRightLat, double? bottomRightLon, string fullImagePath)
        {
            Beeldbankmvc.Models.BeeldbankLinqDataContext beeldBankDB = new Beeldbankmvc.Models.BeeldbankLinqDataContext();
            
            Image mapImage = Image.FromFile(fullImagePath);

            double topLeftLatitude = Convert.ToDouble(topLeftLat);
            double topLeftLongitude = Convert.ToDouble(topLeftLon);
            double bottomRightLatitude = Convert.ToDouble(bottomRightLat);
            double bottomRightLongitude = Convert.ToDouble(bottomRightLon);
            
            double latitudeMultiplication = mapImage.Height / (topLeftLatitude - bottomRightLatitude);
            double longitudeMultiplication = mapImage.Width / (bottomRightLongitude - topLeftLongitude);
            
            var areas = from p in beeldBankDB.BEELDBANK_GEBIEDs
                        orderby p.Id
                        select p;

            using (Graphics g = Graphics.FromImage(mapImage))
            {
                foreach (var area in areas)
                {
                    if (!area.Naam.Equals("Nederland"))
                    {
                        // langs de Y-as
                        int LatitudeTopLeft = Convert.ToInt32((topLeftLatitude - area.linksBovenLatitude) * latitudeMultiplication); // * 646.6580130240811
                        // langs de X-as met begin punt correctie graphic begint met 0,0 rechts boven in
                        int LongitudeTopLeft = Convert.ToInt32((area.linksBovenLongitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119
                        
                        // langs de Y-as
                        int LatitudeBottomRight = Convert.ToInt32((topLeftLatitude - area.rechtsOnderLatitude) * latitudeMultiplication); // * 646.6580130240811
                        // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                        int LongitudeBottomRight = Convert.ToInt32((area.rechtsOnderLongitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119
                        
                        Rectangle r1 = new Rectangle(LongitudeTopLeft, LatitudeTopLeft, (LongitudeBottomRight - LongitudeTopLeft), (LatitudeBottomRight - LatitudeTopLeft));
                        if (area.Plaatje.StartsWith("top"))
                        {
                            Pen line = new Pen(Color.Red);
                            g.DrawRectangle(line, r1);
                        }
                        else
                        {
                            Pen line = new Pen(Color.Blue);
                            g.DrawRectangle(line, r1);
                        }
                    }
                }
            }

            return mapImage;
        }

        public static AreaModel renderImageMapForMapIndex(double topLeftLat, double topLeftLon, double bottomRightLat, double bottomRightLon, string fullImagePath)
        {
            Beeldbankmvc.Models.BeeldbankLinqDataContext beeldBankDB = new Beeldbankmvc.Models.BeeldbankLinqDataContext();

            Image mapImage = Image.FromFile(fullImagePath);

            double topLeftLatitude = Convert.ToDouble(topLeftLat);
            double topLeftLongitude = Convert.ToDouble(topLeftLon);
            double bottomRightLatitude = Convert.ToDouble(bottomRightLat);
            double bottomRightLongitude = Convert.ToDouble(bottomRightLon);
            
            double latitudeMultiplication = mapImage.Height / (topLeftLatitude - bottomRightLatitude);
            double longitudeMultiplication = mapImage.Width / (bottomRightLongitude - topLeftLongitude);

            var areas = from p in beeldBankDB.BEELDBANK_GEBIEDs
                        orderby p.Id descending
                        select p;

            AreaModel areaModel = new AreaModel();

            areaModel.topLeftLatitude = topLeftLatitude;
            areaModel.topLeftLongitude = topLeftLongitude;
            areaModel.topRightLatitude = bottomRightLatitude;
            areaModel.topRightLongitude = bottomRightLongitude;
            areaModel.areaName = fullImagePath;

            using (Graphics g = Graphics.FromImage(mapImage))
            {
                foreach (var area in areas)
                {
                    // langs de Y-as
                    int LatitudeTopLeft = Convert.ToInt32((topLeftLatitude - area.linksBovenLatitude) * latitudeMultiplication); // * 646.6580130240811
                    // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                    int LongitudeTopLeft = Convert.ToInt32((area.linksBovenLongitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119
                    
                    // langs de Y-as
                    int LatitudeBottomRight = Convert.ToInt32((topLeftLatitude - area.rechtsOnderLatitude) * latitudeMultiplication); // * 646.6580130240811
                    // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                    int LongitudeBottomRight = Convert.ToInt32((area.rechtsOnderLongitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119
                    
                    LocationArea loc = new LocationArea();
                    loc.Id = area.Id;
                    loc.xTopLeft = LongitudeTopLeft;
                    loc.yTopLeft = LatitudeTopLeft;

                    loc.xBottomRight = LongitudeBottomRight;
                    loc.yBottomRight = LatitudeBottomRight;

                    loc.Title = area.Naam;

                    areaModel.areaList.Add(loc);
                }
            }

            return areaModel;
        }

        public static Image drawDotsOnMap(double? topLeftLat, double? topLeftLon, double? topRightLat, double? topRightLon, string fullImagePath, string fromDate, string toDate, bool isEdit, int mapId)
        {
            DateTime? realisatieFrom = null;
            if (!String.IsNullOrEmpty(fromDate))
                realisatieFrom = Convert.ToDateTime(fromDate);
            else
                realisatieFrom = Convert.ToDateTime("1-1-1900");

            DateTime? realisatieTo = null;
            if (!String.IsNullOrEmpty(toDate))
                realisatieTo = Convert.ToDateTime(toDate);
            else
                realisatieTo = DateTime.Now;

            Beeldbankmvc.Models.BeeldbankLinqDataContext beeldBankDB = new Beeldbankmvc.Models.BeeldbankLinqDataContext();

            Image mapImage = Image.FromFile(fullImagePath);

            double topLeftLatitude = Convert.ToDouble(topLeftLat);
            double topLeftLongitude = Convert.ToDouble(topLeftLon);
            double topRightLatitude = Convert.ToDouble(topRightLat);
            double topRightLongitude = Convert.ToDouble(topRightLon);

            double latitudeMultiplication = mapImage.Height / (topLeftLatitude - topRightLatitude);
            double longitudeMultiplication = mapImage.Width / (topRightLongitude - topLeftLongitude);

            GebiedRepository gebiedRepository = new GebiedRepository();

            if (isEdit)
            {
                var locations = gebiedRepository.getReferenceLocationsFromMediaObjects(topLeftLatitude, topLeftLongitude, topRightLatitude, topRightLongitude, realisatieFrom, realisatieTo);

                // Only show a subset of dots if there are more then specified number of results
                if (locations.Count() > Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()))
                {
                    int Modulo = Convert.ToInt32(locations.Count() / Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()));
                    locations = gebiedRepository.reduceLocationsFromMediaObjects(locations, Modulo);
                }

                using (Graphics g = Graphics.FromImage(mapImage))
                {
                    foreach (var location in locations)
                    {
                        // langs de Y-as
                        int LatitudeTopLeft = Convert.ToInt32((topLeftLatitude - location.Latitude) * latitudeMultiplication); // * 646.6580130240811
                        // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                        int LongitudeTopLeft = Convert.ToInt32((location.Longitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119

                        Rectangle r1 = new Rectangle(LongitudeTopLeft, LatitudeTopLeft, 7, 7);
                        g.FillEllipse(Brushes.Red, r1);
                    }
                }
            }
            else
            {
                var locations = gebiedRepository.getLocationsFromView(mapId, realisatieFrom, realisatieTo);

                // Only show a subset of dots if there are more then specified number of results
                if (locations.Count() > Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()))
                {
                    int Modulo = Convert.ToInt32(locations.Count() / Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()));
                    locations = gebiedRepository.reduceLocationsFromView(locations, Modulo);
                }

                using (Graphics g = Graphics.FromImage(mapImage))
                {
                    foreach (var location in locations)
                    {
                        // langs de Y-as
                        int LatitudeTopLeft = Convert.ToInt32((topLeftLatitude - location.Latitude) * latitudeMultiplication); // * 646.6580130240811
                        // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                        int LongitudeTopLeft = Convert.ToInt32((location.Longitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119

                        Rectangle r1 = new Rectangle(LongitudeTopLeft, LatitudeTopLeft, 7, 7);
                        g.FillEllipse(Brushes.Red, r1);
                    }
                }
            }

            return mapImage;
        }

        public static Image drawOneDotOnMap(double? topLeftLat, double? topLeftLon, double? topRightLat, double? topRightLon, string fullImagePath, int mapId, int mediaObjectId)
        {
            Beeldbankmvc.Models.BeeldbankLinqDataContext beeldBankDB = new Beeldbankmvc.Models.BeeldbankLinqDataContext();

            Image mapImage = Image.FromFile(fullImagePath); ;
            BEELDBANK_GEBIED beeldbankGebied = new BEELDBANK_GEBIED();

            double topLeftLatitude = Convert.ToDouble(topLeftLat);
            double topLeftLongitude = Convert.ToDouble(topLeftLon);
            double topRightLatitude = Convert.ToDouble(topRightLat);
            double topRightLongitude = Convert.ToDouble(topRightLon);

            double latitudeMultiplication = mapImage.Height / (topLeftLatitude - topRightLatitude);
            double longitudeMultiplication = mapImage.Width / (topRightLongitude - topLeftLongitude);

            MediaObjectRepository mediaObjectRepository = new MediaObjectRepository();

            BEELDBANK_MEDIAOBJECT mediaObject = mediaObjectRepository.FindOne(mediaObjectId);

            using (Graphics g = Graphics.FromImage(mapImage))
            {
                // langs de Y-as
                int LatitudeTopLeft = Convert.ToInt32((topLeftLatitude - mediaObject.Latitude) * latitudeMultiplication); // * 646.6580130240811
                // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                int LongitudeTopLeft = Convert.ToInt32((mediaObject.Longitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119

                Rectangle r1 = new Rectangle(LongitudeTopLeft-13, LatitudeTopLeft-13, 27, 27);
                g.FillEllipse(Brushes.Black, r1);

                Rectangle r2 = new Rectangle(LongitudeTopLeft-10, LatitudeTopLeft-10, 22, 22);
                g.FillEllipse(Brushes.Yellow, r2);

                Rectangle r3 = new Rectangle(LongitudeTopLeft-5, LatitudeTopLeft-5, 11, 11);
                g.FillEllipse(Brushes.Black, r3);
            }

            return mapImage;
        }

        public static LocationsModel renderImageMapForMap(double topLeftLat, double topLeftLon, double topRightLat, double topRightLon, string fullImagePath, string areaName, string fromDate, string toDate, bool isEdit, int mapId)
        {
            DateTime? realisatieFrom = null;
            if (!String.IsNullOrEmpty(fromDate))
                realisatieFrom = Convert.ToDateTime(fromDate);
            else
                realisatieFrom = Convert.ToDateTime("1-1-1900");

            DateTime? realisatieTo = null;
            if (!String.IsNullOrEmpty(toDate))
                realisatieTo = Convert.ToDateTime(toDate);
            else
                realisatieTo = DateTime.Now;

            Beeldbankmvc.Models.BeeldbankLinqDataContext beeldBankDB = new Beeldbankmvc.Models.BeeldbankLinqDataContext();

            Image mapImage = Image.FromFile(fullImagePath);

            double topLeftLatitude = Convert.ToDouble(topLeftLat);
            double topLeftLongitude = Convert.ToDouble(topLeftLon);
            double topRightLatitude = Convert.ToDouble(topRightLat);
            double topRightLongitude = Convert.ToDouble(topRightLon);

            double latitudeMultiplication = mapImage.Height / (topLeftLatitude - topRightLatitude);
            double longitudeMultiplication = mapImage.Width / (topRightLongitude - topLeftLongitude);

            GebiedRepository gebiedRepository = new GebiedRepository();
            LocationsModel locationModel = new LocationsModel();
            
            // use full media object table for edit and temp tables for view 
            // TODO: see if copy to model can be made genaric
            //
            if (isEdit)
            {
                var availableYears = gebiedRepository.getAvailableYearsFromMediaObjects(topLeftLatitude, topLeftLongitude, topRightLatitude, topRightLongitude);
                // Only fetch hidden objects for reference and positioning of the map relative to known locations
                var locations = gebiedRepository.getReferenceLocationsFromMediaObjects(topLeftLatitude, topLeftLongitude, topRightLatitude, topRightLongitude, realisatieFrom, realisatieTo);
                // Only show a subset of dots if there are more then specified number of results
                IEnumerable<BEELDBANK_MEDIAOBJECT> locationsDraw = null;

                if (locations.Count() > Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()))
                {
                    int Modulo = Convert.ToInt32(locations.Count() / Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()));
                    locations = gebiedRepository.reduceLocationsFromMediaObjects(locations, Modulo);
                }
                locationsDraw = locations;



                locationModel.topLeftLatitude = topLeftLatitude;
                locationModel.topLeftLongitude = topLeftLongitude;
                locationModel.topRightLatitude = topRightLatitude;
                locationModel.topRightLongitude = topRightLongitude;
                locationModel.imageName = Regex.Split(fullImagePath, @"\\").Last();
                locationModel.areaName = areaName;
                locationModel.FromDate = Convert.ToDateTime(realisatieFrom);
                locationModel.ToDate = Convert.ToDateTime(realisatieTo);

                foreach (var year in availableYears)
                    locationModel.yearList.Add(year.Key);

                // fill the list of ID without being reduced
                foreach (var location in locations.OrderBy(p => p.Titel))
                    locationModel.locationList.Add(location.Id);

                using (Graphics g = Graphics.FromImage(mapImage))
                {
                    foreach (var location in locationsDraw)
                    {
                        // langs de Y-as
                        int LatitudeTopLeft = Convert.ToInt32((topLeftLatitude - location.Latitude) * latitudeMultiplication); // * 646.6580130240811
                        // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                        int LongitudeTopLeft = Convert.ToInt32((location.Longitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119

                        Location loc = new Location();
                        loc.Id = location.Id;
                        loc.x = LongitudeTopLeft;
                        loc.y = LatitudeTopLeft;
                        loc.Title = location.Titel;

                        locationModel.locationListDraw.Add(loc);
                    }
                }
            }
            else
            {
                var availableYears = gebiedRepository.getAvailableYearsFromView(mapId);
                var locations = gebiedRepository.getLocationsFromView(mapId, realisatieFrom, realisatieTo);
                // Only show a subset of dots if there are more then specified number of results
                IEnumerable<BEELDBANK_GEBIED_INDEX> locationsDraw = null;

                if (locations.Count() > Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()))
                {
                    int Modulo = Convert.ToInt32(locations.Count() / Convert.ToInt32(ConfigurationManager.AppSettings["DotsPerGebied"].ToString()));
                    locations = gebiedRepository.reduceLocationsFromView(locations, Modulo);
                }
                locationsDraw = locations;

                locationModel.topLeftLatitude = topLeftLatitude;
                locationModel.topLeftLongitude = topLeftLongitude;
                locationModel.topRightLatitude = topRightLatitude;
                locationModel.topRightLongitude = topRightLongitude;
                locationModel.imageName = Regex.Split(fullImagePath, @"\\").Last();
                locationModel.areaName = areaName;
                locationModel.FromDate = Convert.ToDateTime(realisatieFrom);
                locationModel.ToDate = Convert.ToDateTime(realisatieTo);

                foreach (var year in availableYears)
                    locationModel.yearList.Add(year.Key);

                // fill the list of ID without being reduced
                foreach (var location in locations.OrderBy(p => p.Titel))
                    locationModel.locationList.Add(location.Id);

                using (Graphics g = Graphics.FromImage(mapImage))
                {
                    foreach (var location in locationsDraw)
                    {
                        // langs de Y-as
                        int LatitudeTopLeft = Convert.ToInt32((topLeftLatitude - location.Latitude) * latitudeMultiplication); // * 646.6580130240811
                        // langs de X-as metbegin punt correctie graphic begint met 0,0 rechts boven in
                        int LongitudeTopLeft = Convert.ToInt32((location.Longitude - topLeftLongitude) * longitudeMultiplication); //* 492.0120120120119

                        Location loc = new Location();
                        loc.Id = location.Id;
                        loc.x = LongitudeTopLeft;
                        loc.y = LatitudeTopLeft;
                        loc.Title = location.Titel;

                        locationModel.locationListDraw.Add(loc);
                    }
                }
            }

            return locationModel;
        }
    }
}